/*
 * File:   pipeline_io_test.hpp
 * Author: picci
 *
 * Created on 25 settembre 2010, 11.35
 */

#define BOOST_TEST_MODULE pipeline facility test
#include <boost/test/included/unit_test.hpp>

#include <string>

#include <boost/any.hpp>

#include <cv.h>

#include "prj_definitions.h"
#include "pipeline/pipeline_io.h"

struct pipeline_io_fixture{
    pipeline_io_fixture(){
        held_str = new std::string("held value");
        assigned_held_str = new std::string("assigned held value");

        held = new boost::any(held_str);
        assigned_held = new boost::any(assigned_held_str);

        el1 = new NAMESPACE::GenericIOElement();
        el1->setElement(held);
        el1->setIOKey("test", "IOElement");

        copy_el1 = new NAMESPACE::GenericIOElement( *(dynamic_cast<NAMESPACE::GenericIOElement*>(el1)) );

        assigned_el1 = new NAMESPACE::GenericIOElement();
        assigned_el1->setElement(assigned_held);
        assigned_el1->setIOKey("test", "assignedIOElement");

        assigned_el12 = new NAMESPACE::GenericIOElement();

        no_el1 = new NAMESPACE::GenericIOElement();
    }

    ~pipeline_io_fixture(){
        delete el1;
        delete copy_el1;
        delete assigned_el1;
        delete assigned_el12;
        delete no_el1;

        delete held;
        delete assigned_held;

        delete held_str;
        delete assigned_held_str;
    }

    NAMESPACE::IOElement *el1, *copy_el1, *assigned_el1, *assigned_el12, *no_el1;

    std::string* held_str;
    std::string* assigned_held_str;

    boost::any* held;
    boost::any* assigned_held;
};

BOOST_FIXTURE_TEST_SUITE(pipeline_io_test, pipeline_io_fixture)

BOOST_AUTO_TEST_SUITE(GenericIOElement_test)

BOOST_AUTO_TEST_CASE(GenericIOElement_constructors_test){
    BOOST_CHECK( &(el1->getElement()) == &(copy_el1->getElement()) );
    BOOST_CHECK(el1->getIOKey() == copy_el1->getIOKey());
    BOOST_CHECK(*el1 == *copy_el1);


    /* Double assignement is used to test if operator= correctly returns the self
     * reference
     */
    dynamic_cast<NAMESPACE::GenericIOElement&>(*assigned_el12) = \
    dynamic_cast<NAMESPACE::GenericIOElement&>(*assigned_el1)  = \
    dynamic_cast<const NAMESPACE::GenericIOElement&>(*el1);

    BOOST_CHECK(assigned_held != 0);

    BOOST_CHECK( &(el1->getElement()) == &(assigned_el1->getElement()) );
    BOOST_CHECK(el1->getIOKey() == assigned_el1->getIOKey());
    BOOST_CHECK(*el1 == *assigned_el1);
    BOOST_CHECK(*el1 == *assigned_el12);
}

BOOST_AUTO_TEST_CASE(GenericIOElement_getElement_test){
    std::string* retrieved_str_ptr = boost::any_cast<std::string*>(el1->getElement());
    boost::any* retrieved = &(el1->getElement());

    BOOST_CHECK(*retrieved_str_ptr == *held_str);
    BOOST_CHECK(retrieved_str_ptr == held_str);

    BOOST_CHECK(held == retrieved);

    BOOST_REQUIRE_THROW(no_el1->getElement(), NAMESPACE::bad_element);
}

BOOST_AUTO_TEST_CASE(HandledIOElement_test){
    cv::Mat* m = new cv::Mat();
    NAMESPACE::IOKey k;
    k.set_key("test", "IOElement");
    k.setType(typeid(cv::Mat));
    NAMESPACE::HandledIOElement* hie = new NAMESPACE::HandledIOElement(m, k);

    NAMESPACE::HandledIOElement* copy_hie = new NAMESPACE::HandledIOElement(*hie);

    NAMESPACE::HandledIOElement *assigned_hie = new NAMESPACE::HandledIOElement(*hie), assigned_hie2;
    assigned_hie2 = *assigned_hie = *hie;

    BOOST_CHECK(*hie == *copy_hie);
    BOOST_CHECK(*hie == *assigned_hie);
    BOOST_CHECK(*hie == assigned_hie2);

    delete hie;
    delete copy_hie;
    delete assigned_hie;

    delete m;
}

BOOST_AUTO_TEST_CASE(NumericIOElement_test){
    NAMESPACE::NumericIOElement nie(1);
    NAMESPACE::NumericIOElement copy_nie = NAMESPACE::NumericIOElement(nie);

    NAMESPACE::NumericIOElement assigned_nie(3.0), assigned_nie2(2.0);
    assigned_nie2 = assigned_nie = nie;

    BOOST_CHECK(nie == copy_nie);
    BOOST_CHECK(nie == assigned_nie);
    BOOST_CHECK(nie == assigned_nie2);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()

